/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.ui.util;

import java.util.HashMap;
import java.util.Map;

import javax.swing.JTable;
import javax.swing.SwingUtilities;

/**
 * 
 * @author mathieu bolletta
 * This class handle columns width of a JTable, setting dimensions to 0 to make it invisible <BR>
 * providing a restoring function to original state while setting columns visible
 * 
 */
public class ColumnWidthsHandler {
	
	private class ColumnWidths {
		protected Integer headerWidth;
		protected Integer minHeaderWidth;
		protected Integer preferredHeaderWidth;
		protected Integer maxHeaderWidth;
		
		protected Integer colWith;
		protected Integer minColWith;
		protected Integer preferredColWith;
		protected Integer maxColWith;		
	}
	
	private Map<Integer, ColumnWidths> initialStates =new HashMap<Integer, ColumnWidths>();

	private JTable table;
	
	/**
	 * Only available constructor
	 * @param table: The JTable you want to handle
	 */
	public ColumnWidthsHandler( JTable table ) {
		this.table = table;
		copySizes();
	}
	
	/**
	 * 
	 * @param visible: Setting a column visible, passing true to the visible argument, or invisible passing false
	 * @param columnIndex: The column index
	 */
	
	public void setVisible( boolean visible, Integer columnIndex ){
		
		if ( columnIndex >= table.getColumnCount() ) {
			throw new IllegalArgumentException("Column index out of bounds!");
		}
		
		ColumnWidths colWith =initialStates.get(columnIndex);
		if ( visible ) {
			setOptimalPreferredSizes(columnIndex);	
			table.getColumnModel().getColumn(columnIndex).setMaxWidth( colWith.maxColWith!=null ? colWith.maxColWith:0 );
			table.getColumnModel().getColumn(columnIndex).setPreferredWidth( colWith.preferredColWith!=null ? colWith.preferredColWith:0 );
			table.getColumnModel().getColumn(columnIndex).setMinWidth( colWith.minColWith!=null ? colWith.minColWith:0 );
			table.getColumnModel().getColumn(columnIndex).setWidth( colWith.colWith!=null ? colWith.colWith:0 );
			
			table.getTableHeader().getColumnModel().getColumn(columnIndex).setMaxWidth( colWith.maxHeaderWidth!=null ? colWith.maxHeaderWidth:0 );
			table.getTableHeader().getColumnModel().getColumn(columnIndex).setMinWidth( colWith.minHeaderWidth!=null ? colWith.minHeaderWidth:0 );
			table.getTableHeader().getColumnModel().getColumn(columnIndex).setPreferredWidth( colWith.preferredHeaderWidth!=null ? colWith.preferredHeaderWidth:0 );
			table.getTableHeader().getColumnModel().getColumn(columnIndex).setWidth( colWith.headerWidth!=null ? colWith.headerWidth:0 );					
			
		} else {
			table.getColumnModel().getColumn(columnIndex).setMaxWidth(0);
			table.getColumnModel().getColumn(columnIndex).setPreferredWidth(0);
			table.getColumnModel().getColumn(columnIndex).setMinWidth(0);
			table.getColumnModel().getColumn(columnIndex).setWidth(0);
			
			table.getTableHeader().getColumnModel().getColumn(columnIndex).setMaxWidth(0);
			table.getTableHeader().getColumnModel().getColumn(columnIndex).setMinWidth(0);
			table.getTableHeader().getColumnModel().getColumn(columnIndex).setPreferredWidth(0);
			table.getTableHeader().getColumnModel().getColumn(columnIndex).setWidth(0);
		}
	}
	
	/**
	 * Backup the whole table columns states
	 */
	private void copySizes() {
		
		for ( Integer i =0; i < table.getColumnCount(); i++ ){
			
			ColumnWidths colWiths = new ColumnWidths();
			colWiths.colWith =table.getColumnModel().getColumn(i).getMaxWidth();
			colWiths.minColWith =table.getColumnModel().getColumn(i).getPreferredWidth();
			colWiths.preferredColWith =table.getColumnModel().getColumn(i).getMinWidth();
			colWiths.maxColWith =table.getColumnModel().getColumn(i).getWidth();
			
			colWiths.maxHeaderWidth = table.getTableHeader().getColumnModel().getColumn(i).getMaxWidth();
			colWiths.minHeaderWidth =table.getTableHeader().getColumnModel().getColumn(i).getMinWidth();
			colWiths.preferredColWith =table.getTableHeader().getColumnModel().getColumn(i).getPreferredWidth();
			colWiths.colWith =table.getTableHeader().getColumnModel().getColumn(i).getWidth();
			
			initialStates.put(i, colWiths);
			
		}
		
	}
	
	/**
	 * Compute the optimal width depending on the column content, applying new sizes
	 * @param columnIndex: The column where you want to do this
	 */
	private void setOptimalPreferredSizes( Integer columnIndex ) {
		String greatestString = "";
		
		for ( int row = 0; row < table.getRowCount(); row++ ) {
			
			Object currentValue =table.getValueAt(row,columnIndex);
			
			if ( String.valueOf( currentValue).length() > greatestString.length() ){
				greatestString =String.valueOf(currentValue);
			}
			
			if ( currentValue != null ){
				Integer optimalWidth =SwingUtilities.computeStringWidth(table.getFontMetrics( table.getFont() ), greatestString);
				initialStates.get( columnIndex ).preferredColWith =optimalWidth;
				initialStates.get( columnIndex ).minColWith =optimalWidth;
				initialStates.get( columnIndex ).colWith =optimalWidth;
				initialStates.get( columnIndex ).preferredHeaderWidth =optimalWidth;
				initialStates.get( columnIndex ).minHeaderWidth =optimalWidth;
				initialStates.get( columnIndex ).headerWidth =optimalWidth;
			}
		}
			
	}
}
